#!/bin/dash

#Copyright (c) 2014 Luigi Tarenga <luigi.tarenga@gmail.com>
#Distributed under the terms of a MIT license.

#append-entry:
#input  term leader_id prev_log_index prev_log_term entry_term entry_command entry leader_commit
#        $1   $2        $3             $4            $5         $6            $7    $8
#output term success

if [ -d temp/master_lockdir ] ; then
   read current_term    < state/current_term
   read commit_index    < temp/commit_index
   read server_role     < temp/server_role
   read current_leader  < temp/current_leader
   read last_log_index  < state/last_log_index

   entry_index=$(($3+1))

   if [ "$1" -gt "$current_term" ] ; then
      current_term="$1"
      echo follower > temp/server_role
      echo "$current_term" > state/current_term
   fi

   if [ "$1" -eq "$current_term" ] ; then
      if [ "$server_role" = "candidate" ] ; then
         echo follower > temp/server_role
      fi

      log_diverge="true"
      if [ -f state-machine-log/"$3"/"$4" ] ; then
         log_diverge="false"
      elif [ -f state-machine-snapshot/cur/last_included_index -a -f state-machine-snapshot/cur/last_included_term ] ; then
         read last_included_index < state-machine-snapshot/cur/last_included_index
         read last_included_term  < state-machine-snapshot/cur/last_included_term
         if [ "$last_included_index" -eq "$3" -a "$last_included_term" -eq "$4" ] ; then
            log_diverge="false"
         fi
      fi

      if [ "$log_diverge" = "false" ] ; then
         rm -rf state-machine-log/$entry_index
         if [ "$6" = "conf_old_new" ] ; then
            #received a joint consensus command (Cold.new)
            echo "$7" > conf/cluster_nodes_new
         elif [ "$6" = "conf_new" ] ; then
            #switch to new configuration
            mv conf/cluster_nodes_new conf/cluster_nodes
         fi

         #append entry if not null (null = heartbeat)
         if [ -n "$6" ] ; then
            mkdir -p state-machine-log/$entry_index
            echo "$6 $7" > state-machine-log/$entry_index/$5
            last_log_index=$entry_index
            echo "$last_log_index" > state/last_log_index
         fi

         if [ "$8" -gt "$commit_index" ] ; then
            if [ "$8" -lt "$last_log_index" ] ; then
               echo "$8" > temp/commit_index
            else
               echo "$last_log_index" > temp/commit_index
            fi
         fi
         #sync
         echo "$current_term" true

      else
         #my log diverge, send me a previous log!
         rm -rf state-machine-log/$entry_index
         echo "$current_term" false
      fi
      [ "$2" != "$current_leader" ] && echo "$2" > temp/current_leader
      cp conf/election_timeout temp/election_timeout

   else
      #return error with updated term
      echo $current_term false
   fi
else
   #no process running here, return error
   echo 0 false
fi
